/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.warrantyhotel.android.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

/**
 * Helper class for fetching and disk-caching images from the web.
 */
public class BitmapUtils {
	private static final String TAG = "BitmapUtils";

	// TODO: for concurrent connections, DefaultHttpClient isn't great, consider
	// other options
	// that still allow for sharing resources across bitmap fetches.

	public static interface OnFetchCompleteListener {
		public void onFetchComplete(Object cookie, Bitmap result);
	}

	/**
	 * Only call this method from the main (UI) thread. The
	 * {@link OnFetchCompleteListener} callback be invoked on the UI thread, but
	 * image fetching will be done in an {@link AsyncTask}.
	 */
	public static void fetchImage(final Context context, final String url, final OnFetchCompleteListener callback) {
		 fetchImage(context, url, null, null, callback);
//		fetchImage1(context, url, null, null, callback);

	}

	/**
	 * Only call this method from the main (UI) thread. The
	 * {@link OnFetchCompleteListener} callback be invoked on the UI thread, but
	 * image fetching will be done in an {@link AsyncTask}.
	 * 
	 * @param cookie
	 *            An arbitrary object that will be passed to the callback.
	 */
	public static void fetchImage(final Context context, final String url, final BitmapFactory.Options decodeOptions,
			final Object cookie, final OnFetchCompleteListener callback) {
		new AsyncTask<String, Void, Bitmap>() {
			@Override
			protected Bitmap doInBackground(String... params) {
				final String url = params[0];
				if (TextUtils.isEmpty(url)) {
					return null;
				}

				// First compute the cache key and cache file path for this URL
				File cacheFile = null;
				try {
					MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
					mDigest.update(url.getBytes());
					final String cacheKey = bytesToHexString(mDigest.digest());
					if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
						cacheFile = new File(Environment.getExternalStorageDirectory() + File.separator + "Android"
								+ File.separator + "data" + File.separator + context.getPackageName() + File.separator + "cache"
								+ File.separator + "bitmap_" + cacheKey + ".tmp");
					}
				} catch (NoSuchAlgorithmException e) {
					// Oh well, SHA-1 not available (weird), don't cache
					// bitmaps.
				}

				if (cacheFile != null && cacheFile.exists()) {
					Bitmap cachedBitmap = BitmapFactory.decodeFile(cacheFile.toString(), decodeOptions);
					if (cachedBitmap != null) {
						return cachedBitmap;
					}
				}

				InputStream is = null;
				try {

					is = new URL(url).openStream();
					final byte[] respBytes = IOUtil.readBytes(is);

					// Write response bytes to cache.
					if (cacheFile != null) {
						try {
							cacheFile.getParentFile().mkdirs();
							cacheFile.createNewFile();
							FileOutputStream fos = new FileOutputStream(cacheFile);
							fos.write(respBytes);
							fos.close();
						} catch (FileNotFoundException e) {
							Log.w(TAG, "Error writing to bitmap cache: " + cacheFile.toString(), e);
						} catch (IOException e) {
							Log.w(TAG, "Error writing to bitmap cache: " + cacheFile.toString(), e);
						}
					}
					// Decode the bytes and return the bitmap.
					return BitmapFactory.decodeByteArray(respBytes, 0, respBytes.length, decodeOptions);
				} catch (Exception e) {
					Log.w(TAG, "Problem while loading image: " + e.toString(), e);
				} finally {
					IOUtil.closeQuietly(is);
				}
				return null;
			}

			@Override
			protected void onPostExecute(Bitmap result) {
				callback.onFetchComplete(cookie, result);
			}
		}.execute(url);
	}

	public static void fetchImage1(final Context context, final String url, final BitmapFactory.Options decodeOptions,
			final Object cookie, final OnFetchCompleteListener callback) {

		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				// super.handleMessage(msg);
				Log.v("image", "image");
				callback.onFetchComplete(cookie, (Bitmap) msg.obj);
			}
		};

		Thread t = new Thread() {
			@Override
			public void run() {

				if (TextUtils.isEmpty(url)) {
					handler.sendMessage(handler.obtainMessage(1, null));
					// return null;
				}

				// First compute the cache key and cache file path for this URL
				// File cacheFile = null;
				// try {
				// MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
				// mDigest.update(url.getBytes());
				// final String cacheKey = bytesToHexString(mDigest.digest());
				// if
				// (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
				// {
				// cacheFile = new
				// File(Environment.getExternalStorageDirectory() +
				// File.separator + "Android"
				// + File.separator + "data" + File.separator +
				// context.getPackageName() + File.separator + "cache"
				// + File.separator + "bitmap_" + cacheKey + ".tmp");
				// }
				// } catch (NoSuchAlgorithmException e) {
				// e.printStackTrace();
				// }
				// if (cacheFile != null && cacheFile.exists()) {
				// Bitmap cachedBitmap =
				// BitmapFactory.decodeFile(cacheFile.toString(),
				// decodeOptions);
				// if (cachedBitmap != null) {
				// handler.sendMessage(handler.obtainMessage(1, cachedBitmap));
				// }
				// }
				InputStream is = null;
				try {

					is = new URL(url).openStream();
					final byte[] respBytes = IOUtil.readBytes(is);
					// Write response bytes to cache.
//					if (cacheFile != null) {
//						try {
//							cacheFile.getParentFile().mkdirs();
//							cacheFile.createNewFile();
//							FileOutputStream fos = new FileOutputStream(cacheFile);
//							fos.write(respBytes);
//							fos.close();
//						} catch (FileNotFoundException e) {
//							Log.w(TAG, "Error writing to bitmap cache: " + cacheFile.toString(), e);
//						} catch (IOException e) {
//							Log.w(TAG, "Error writing to bitmap cache: " + cacheFile.toString(), e);
//						}
//					}
					// Decode the bytes and return the bitmap.
					handler.sendMessage(handler.obtainMessage(1,
							BitmapFactory.decodeByteArray(respBytes, 0, respBytes.length, decodeOptions)));
					// return BitmapFactory.decodeByteArray(respBytes, 0,
					// respBytes.length, decodeOptions);
				} catch (Exception e) {
					Log.w(TAG, "Problem while loading image: " + e.toString(), e);
				} finally {
					IOUtil.closeQuietly(is);
				}
				handler.sendMessage(handler.obtainMessage(1, null));
			}
		};
		t.start();

	}

	private static String bytesToHexString(byte[] bytes) {
		// http://stackoverflow.com/questions/332079
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(0xFF & bytes[i]);
			if (hex.length() == 1) {
				sb.append('0');
			}
			sb.append(hex);
		}
		return sb.toString();
	}

}
